import os
import json
import requests
import dotenv
import os.path
from openai import OpenAI

# 加载.env文件
dotenv.load_dotenv(os.path.join(os.path.dirname(os.path.abspath(__file__)), '.env'))

class DocumentAnalyzer:
    def __init__(self, api_key, model, base_url):
        self.api_key = api_key
        self.model = model
        self.base_url = base_url
        # 确保base_url以/结尾
        if not self.base_url.endswith('/'):
            self.base_url += '/'
        
        # 创建OpenAI客户端
        self.client = OpenAI(
            api_key=self.api_key,
            base_url=self.base_url
        )

    def analyze_files(self, file_tree, task_id, extract_folder):
        """
        分析文件树并生成业务代码分类
        """
        # 格式化文件树内容
        file_content = "\n".join(file_tree)
        
        # 设置分析提示词
        system_message = "你是一位专业的后端代码架构分析专家，请帮助分析项目结构。"
        prompt = f"""
        以下是代码文件树内容:
                            
        {file_content}

        根据上述代码文件树，分析出业务代码，并重新生成业务代码文件树

        限制：
        1. 不要输出任何解释，只需要输出文件目录树，严格遵守输出格式
        2. 将功能模块的代码写在一起，不要分开，不同的功能用空行隔开
        3. 后端配置和工具类放到最后面，排除sql文件
        4. 前端的第三方库文件、公共组件、仓库和工具类全部过滤，输出格式中标记的 admin 和 front 路径不是固定的，必须遵守真实文件树的目录结构输出
        5. python 项目注意过滤掉 .pth 模型文件
        6. 输出的目录将用于严格路径匹配，请务必保证目录的准确性

        输出格式：

        用户管理
        xxx/xxx/xxx/xxx/xxx/user/controller/UserController.java
        xxx/xxx/xxx/xxx/xxx/user/service/UserService.java
        xxx/xxx/xxx/xxx/xxx/user/service/impl/UserServiceImpl.java
        xxx/xxx/xxx/xxx/xxx/user/view/UserVO.java
        xxx/xxx/xxx/xxx/xxx/user/model/User.java
        xxx/xxx/xxx/xxx/xxx/front/pages/user/formAdd.vue
        xxx/xxx/xxx/xxx/xxx/front/pages/user/formModel.vue
        xxx/xxx/xxx/xxx/xxx/front/pages/user/list.vue
        xxx/xxx/xxx/xxx/xxx/admin/pages/user/add.vue
        xxx/xxx/xxx/xxx/xxx/admin/pages/user/list.vue

        角色管理
        xxx/xxx/xxx/xxx/xxx/role/controller/RoleController.java
        xxx/xxx/xxx/xxx/xxx/role/service/RoleService.java
        xxx/xxx/xxx/xxx/xxx/role/service/impl/RoleServiceImpl.java
        xxx/xxx/xxx/xxx/xxx/role/view/RoleVO.java
        xxx/xxx/xxx/xxx/xxx/role/model/Role.java
        xxx/xxx/xxx/xxx/xxx/front/pages/Role/formAdd.vue
        xxx/xxx/xxx/xxx/xxx/front/pages/Role/formModel.vue
        xxx/xxx/xxx/xxx/xxx/front/pages/Role/list.vue
        xxx/xxx/xxx/xxx/xxx/admin/pages/Role/add.vue
        xxx/xxx/xxx/xxx/xxx/admin/pages/Role/list.vue
        ......

        src/xxx/xxx/xxx/xxx/xxx/xxx/config/AlipayConfig.java
        src/xxx/xxx/xxx/xxx/xxx/xxx/config/InterceptorConfig.java
        src/xxx/xxx/xxx/xxx/xxx/xxx/config/MybatisPlusConfig.java
        """

        try:
            # 使用OpenAI客户端API
            response = self.client.chat.completions.create(
                model=self.model,
                messages=[
                    {"role": "system", "content": system_message},
                    {"role": "user", "content": prompt}
                ],
                temperature=0.2
            )
            
            # 保存完整的API响应
            api_response_file = os.path.join(extract_folder, task_id, "api_response.json")
            with open(api_response_file, 'w', encoding='utf-8') as f:
                json.dump(response.dict(), f, ensure_ascii=False, indent=2)
            
            content = response.choices[0].message.content
            
            # 保存原始内容到文本文件
            raw_content_file = os.path.join(extract_folder, task_id, "raw_content.txt")
            with open(raw_content_file, 'w', encoding='utf-8') as f:
                f.write(content)
            
            # 解析结果和分类文件
            return self.parse_and_organize_result(content, task_id, extract_folder)
            
        except Exception as e:
            error_message = f"分析处理出现错误: {str(e)}"
            print(error_message)
            
            # 保存错误信息到文件
            error_file = os.path.join(extract_folder, task_id, "analysis_error.txt")
            with open(error_file, 'w', encoding='utf-8') as f:
                f.write(error_message)
                
            return {"error": str(e)}
            
    def parse_and_organize_result(self, content, task_id, extract_folder):
        """解析AI分析结果并组织文件"""
        try:
            # 分割成不同的功能块
            modules = []
            current_module = {"name": "", "files": []}
            lines = content.strip().split('\n')
            
            # 记录解析过程
            parsing_log = []
            parsing_log.append("开始解析AI返回内容，共 {} 行".format(len(lines)))
            
            current_module_name = ""
            
            for i, line in enumerate(lines):
                line = line.strip()
                parsing_log.append(f"行 {i+1}: '{line}'")
                
                if not line:
                    # 空行表示模块分隔
                    if current_module["name"] and current_module["files"]:
                        modules.append(current_module.copy())
                        parsing_log.append(f"添加模块: {current_module['name']}, 文件数: {len(current_module['files'])}")
                        current_module = {"name": "", "files": []}
                elif not '/' in line and not '\\' in line:  # 检查是否不包含路径分隔符，这是模块名称
                    # 这是模块名称
                    if current_module["name"] and current_module["files"]:
                        modules.append(current_module.copy())
                        parsing_log.append(f"添加模块: {current_module['name']}, 文件数: {len(current_module['files'])}")
                        current_module = {"name": "", "files": []}
                    current_module["name"] = line
                    current_module_name = line
                    parsing_log.append(f"设置当前模块名称: {line}")
                else:
                    # 这是文件路径，将其添加到当前模块
                    if current_module_name:
                        # 确保当前模块有名称
                        if not current_module["name"]:
                            current_module["name"] = current_module_name
                    
                    # 手动添加前缀
                    full_path = f"temp_extracted/{task_id}/{line}"
                    current_module["files"].append(full_path)
                    parsing_log.append(f"添加文件路径: {full_path}")
            
            # 添加最后一个模块
            if current_module["name"] and current_module["files"]:
                modules.append(current_module.copy())
                parsing_log.append(f"添加最后模块: {current_module['name']}, 文件数: {len(current_module['files'])}")
            
            parsing_log.append(f"总共解析出 {len(modules)} 个模块")
            
            # 保存解析日志
            parsing_log_file = os.path.join(extract_folder, task_id, "parsing_log.txt")
            with open(parsing_log_file, 'w', encoding='utf-8') as f:
                f.write("\n".join(parsing_log))
            
            # 整合所有文件路径，用于创建总文件
            all_files = []
            for module in modules:
                all_files.extend(module["files"])
            
            # 创建结果结构
            result = {
                "task_id": task_id,
                "modules": modules,
                "all_files": all_files
            }
            
            # 保存分析结果到文件
            result_file = os.path.join(extract_folder, task_id, "analysis_result.json")
            with open(result_file, 'w', encoding='utf-8') as f:
                json.dump(result, f, ensure_ascii=False, indent=2)
            
            return result
            
        except Exception as e:
            error_message = f"解析AI分析结果时出错: {str(e)}"
            print(error_message)
            
            # 保存错误信息到文件
            error_file = os.path.join(extract_folder, task_id, "parsing_error.txt")
            with open(error_file, 'w', encoding='utf-8') as f:
                f.write(error_message)
                
            return {"error": str(e)}

# 工厂函数，用于创建分析器实例
def create_analyzer(model_id):
    """
    根据模型ID创建对应的分析器实例
    """
    models = {
        "deepseek": {
            "api_key": os.getenv("DEEPSEEK_API_KEY", "sk-2a5ae1ad0ccb4611aa6024a0b9cfc0bd"),
            "model": os.getenv("DEEPSEEK_MODEL", "deepseek-reasoner"),
            "base_url": os.getenv("DEEPSEEK_API_URL", "https://api.deepseek.com")
        },
        "qwen": {
            "api_key": os.getenv("QWEN_API_KEY", "sk-a1e2fb0515624f8d93878fb122ec1160"),
            "model": os.getenv("QWEN_MODEL", "qwen-max-2025-01-25"),
            "base_url": os.getenv("QWEN_API_URL", "https://dashscope.aliyuncs.com/compatible-mode/v1")
        },
        "gemini": {
            "api_key": os.getenv("GEMINI_API_KEY", "AIzaSyAaBLupd1Pe7FQhOVwmuE3qSVj1r6jKMKg"),
            "model": os.getenv("GEMINI_MODEL", "gemini-2.5-flash-preview-04-17"),
            "base_url": os.getenv("GEMINI_API_URL", "https://generativelanguage.googleapis.com/v1beta/openai/")
        },
        "openai": {
            "api_key": os.getenv("OPENAI_API_KEY", ""),
            "model": os.getenv("OPENAI_MODEL", "gpt-4o"),
            "base_url": os.getenv("OPENAI_API_URL", "https://api.openai.com/v1")
        }
    }
    
    if model_id not in models:
        raise ValueError(f"不支持的模型ID: {model_id}")
    
    config = models[model_id]
    return DocumentAnalyzer(
        api_key=config["api_key"],
        model=config["model"],
        base_url=config["base_url"]
    ) 